package com.faceunity;

import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;

import com.faceunity.wrapper.faceunity;
import com.noble.library.dir.DirType;
import com.noble.library.log.PSP;
import com.noble.library.log.PToast;
import com.noble.library.utils.FileUtil;
import com.noble.library.utils.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * faceunity初始化工具类
 * <p>
 * Created by Su on 2017/4/5.
 */
public class MRender {
    private static Context context;
    private static Handler handler;
    static long startTime;

    private static int effectItem;     // 贴纸道具
    private static int facebeautyItem; // 美颜道具
    private static boolean creatingItem; // 载入文件中
    private static boolean ensureCreate = false; // 确保载入中

    private static String[] ITEM_NAMES;  // 道具配表

    private static int frameId;
    private static int w;
    private static int h;

    /**
     * 异步创建faceunity
     */
    public static void create(final Context context) {
        MRender.context = context;
        frameId = 0;

        // 读取道具配表
        ITEM_NAMES = StringUtils.stringToArray(PSP.getInstance().getString("RTC_VIDEO_PROP", ""), ",");

        // faceU的所有Api需要在同一线程调用
        HandlerThread handlerThread = new HandlerThread("MRender");
        handlerThread.start();
        handler = new Handler(handlerThread.getLooper());
        ensureCreated();
    }

    private static void ensureCreated() {
        if (ensureCreate) return;

        final byte[] authdata = authpack.A();
        handler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    faceunity.fuCreateEGLContext();

                    InputStream is = context.getAssets().open("v3.mp3");
                    byte[] v3data = new byte[is.available()];
                    is.read(v3data);
                    is.close();
                    faceunity.fuSetup(v3data, null, authdata);
                    faceunity.fuSetMaxFaces(1);

                    is = context.getAssets().open("face_beautification.mp3");
                    byte[] itemData = new byte[is.available()];
                    is.read(itemData);
                    is.close();
                    facebeautyItem = faceunity.fuCreateItemFromPackage(itemData);
                    ensureCreate = true;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 加载新的二进制头饰文件
     */
    public static void setCurrentItemByPosition(final int itemPosition) {
        creatingItem = true;
        ensureCreated();

        handler.post(new Runnable() {
            @Override
            public void run() {
                int effectItem = MRender.effectItem;
                if (itemPosition > 0) {
                    createEffectItem(itemPosition);
                    destroyEffectItem(effectItem);
                } else {
                    MRender.effectItem = 0;
                    destroyEffectItem(effectItem);
                }
                creatingItem = false;
            }
        });
    }

    /**
     * 加载二进制头饰文件
     */
    private static void createEffectItem(int itemPosition) {
        try {
            if (itemPosition > 0) {
                // 长度超过限制
                if (itemPosition >= ITEM_NAMES.length)
                    itemPosition = ITEM_NAMES.length - 1;
                String filePath = DirType.getDownloadDir() +
                        FileUtil.getFileNameByPath(ITEM_NAMES[itemPosition].trim()) + ".mp3";

                if (!FileUtil.isExist(filePath)) {
                    PToast.showShort("您的道具资源未下载完成，请稍后");
                    // 执行下载的Http在app中，当前暂时无法直接下载
                    return;
                }
                File f = new File(filePath);
                InputStream is = new FileInputStream(f);
                byte[] itemData = new byte[is.available()];
                is.read(itemData);
                is.close();
                effectItem = faceunity.fuCreateItemFromPackage(itemData);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void destroyEffectItem(int effectItem) {
        if (effectItem != 0) {
            faceunity.fuDestroyItem(effectItem);
        }
    }

    public static void destroy() {
        context = null;
        ensureCreate = false;
        handler.post(new Runnable() {
            @Override
            public void run() {
                destroyEffectItem(effectItem);
                effectItem = 0;
                faceunity.fuDestroyItem(facebeautyItem);
                faceunity.fuOnDeviceLost();
                faceunity.fuReleaseEGLContext();
                handler.getLooper().quit();
            }
        });
    }

    // 设置滤镜
    public static void setCurrentFilterByPosition(final String filterName) {
        ensureCreated();
        handler.post(new Runnable() {
            @Override
            public void run() {
                faceunity.fuItemSetParam(facebeautyItem, "filter_name", filterName);
            }
        });
    }

    // 磨皮： 取值范围为0-6，对应7个不同的磨皮程度。可进一步自定义磨皮
    public static void setBlurLevel(final int level) {
        ensureCreated();
        handler.post(new Runnable() {
            @Override
            public void run() {
                faceunity.fuItemSetParam(facebeautyItem, "blur_level", level);
            }
        });
    }

    // 当前滤镜为"nature" 时，设置美白； 当前滤镜为其他风格时，该参数用于控制风格化程度。
    // 取值为大于等于0的浮点数，0为无效果，1为默认效果，大于1为继续增强效果。
    public static void setColorLevel(final int progress, final int max) {
        ensureCreated();
        handler.post(new Runnable() {
            @Override
            public void run() {
                faceunity.fuItemSetParam(facebeautyItem, "color_level", (float) progress / max);
            }
        });
    }

    public static void setRedLevel(final int progress, final int max) {
        ensureCreated();
        handler.post(new Runnable() {
            @Override
            public void run() {
                faceunity.fuItemSetParam(facebeautyItem, "red_level", (float) progress / max);
            }
        });
    }

    public static void setFaceShape(final int level) {
        ensureCreated();
        handler.post(new Runnable() {
            @Override
            public void run() {
                faceunity.fuItemSetParam(facebeautyItem, "face_shape", level);
            }
        });
    }

    public static void setFaceShapeLevel(final int progress, final int max) {
        ensureCreated();
        handler.post(new Runnable() {
            @Override
            public void run() {
                faceunity.fuItemSetParam(facebeautyItem, "face_shape_level", (float) progress / max);
            }
        });
    }

    // 瘦脸 ：取值为大于等于0的浮点数，0为关闭效果，1为默认效果，大于1为进一步增强效果。
    public static void setCheekThinning(final int progress, final int max) {
        ensureCreated();
        handler.post(new Runnable() {
            @Override
            public void run() {
                faceunity.fuItemSetParam(facebeautyItem, "cheek_thinning", (float) progress / max);
            }
        });
    }

    // 大眼： 取值为大于等于0的浮点数，0为关闭效果，1为默认效果，大于1为进一步增强效果。
    public static void setEyeEnlarging(final int progress, final int max) {
        ensureCreated();
        handler.post(new Runnable() {
            @Override
            public void run() {
                faceunity.fuItemSetParam(facebeautyItem, "eye_enlarging", (float) progress / max);
            }
        });
    }


    // 重要，勿删
    public static void renderToI420Image(final byte[] img, final int w, final int h) {
        if (context == null) return;

        if (frameId >= 10 && startTime == 0) {
            startTime = System.currentTimeMillis();
        }

        synchronized (MRender.class) {
            try {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        synchronized (MRender.class) {
                            if (MRender.w != 0 && (MRender.w != w || MRender.h != h)) {
                                faceunity.fuOnDeviceLost();
                            }
                            MRender.w = w;
                            MRender.h = h;

                            faceunity.fuItemSetParam(effectItem, "isAndroid", 1);
                            faceunity.fuRenderToI420Image(img, w, h, frameId++, new int[]{effectItem, facebeautyItem});
                            MRender.class.notifyAll();
                        }
                    }
                });
                MRender.class.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
